package com.teaching.teachingsupport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.teaching.teachingsupport.common.pojo.dataobject.Student;
import com.teaching.teachingsupport.common.pojo.dataobject.Teacher;
import com.teaching.teachingsupport.common.pojo.dataobject.User;
import com.teaching.teachingsupport.common.pojo.dto.request.CreateUserRequest;
import com.teaching.teachingsupport.common.pojo.dto.response.UserPageResponse;
import com.teaching.teachingsupport.common.utils.BeanCover;
import com.teaching.teachingsupport.common.utils.SearchKeyUtil;
import com.teaching.teachingsupport.mapper.studentviewmapper.StudentMapper;
import com.teaching.teachingsupport.mapper.TeacherMapper;
import com.teaching.teachingsupport.mapper.UserMapper;
import com.teaching.teachingsupport.service.service2.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final StudentMapper studentMapper;
    private final TeacherMapper teacherMapper;
    private final BCryptPasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = this.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        return  org.springframework.security.core.userdetails.User
                .withUsername(username)
                .password(user.getPasswordHash())
                .roles(user.getRoleType())
                .build();
    }

    public User findByUsername(String text) {
        return this.query()
                .eq("username", text)
                .one();
    }

    @Override
    public Integer getTotalUserCount() {
        Long count = this.count();
        return count.intValue();
    }

    @Override
    public Integer getDailyActiveUsers() {
        LocalDate today = LocalDate.now();
        Long count = this.query()
                .apply("DATE(last_login) = {0}", today)
                .count();
        return count.intValue();
    }

    @Override
    public Page<UserPageResponse> getUserPage(Integer pageNum, Integer pageSize, String roleType, String grade, String searchKey) {
        log.info("开始查询用户列表 - 页码: {}, 每页数量: {}, 角色类型: {}, 年级: {}, 搜索关键字: {}", 
                pageNum, pageSize, roleType, grade, searchKey);
        
        // 创建分页对象
        Page<User> page = new Page<>(pageNum, pageSize);
        
        // 构建基础查询条件
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        
        // 1. 角色类型过滤
        if (StringUtils.hasText(roleType)) {
            queryWrapper.eq(User::getRoleType, roleType);
            log.debug("添加角色类型过滤条件: {}", roleType);
        }

        // 2. 搜索条件处理
        if (StringUtils.hasText(searchKey)) {
            log.debug("处理搜索关键字: {}", searchKey);
            
            // 2.1 分析搜索关键字类型
            SearchKeyUtil.SearchKeyType keyType = SearchKeyUtil.analyzeSearchKeyType(searchKey);
            log.debug("搜索关键字类型: {}", keyType);
            
            List<Long> matchedUserIds = new ArrayList<>();
            
            // 2.2 根据关键字类型和角色类型决定搜索范围
            switch (keyType) {
                case STUDENT_NO:
                    if (!StringUtils.hasText(roleType) || "学生".equals(roleType)) {
                        // 精确匹配学号
                        List<Student> students = studentMapper.selectList(
                                new LambdaQueryWrapper<Student>()
                                        .eq(Student::getStudentNo, searchKey)
                                        .select(Student::getUserId)
                        );
                        matchedUserIds.addAll(students.stream()
                                .map(Student::getUserId)
                                .collect(Collectors.toList()));
                        log.debug("通过学号精确匹配到的学生数量: {}", matchedUserIds.size());
                    }
                    break;
                    
                case TEACHER_NO:
                    if (!StringUtils.hasText(roleType) || "教师".equals(roleType)) {
                        // 精确匹配教师工号
                        List<Teacher> teachers = teacherMapper.selectList(
                                new LambdaQueryWrapper<Teacher>()
                                        .eq(Teacher::getTeacherNo, searchKey)
                                        .select(Teacher::getUserId)
                        );
                        matchedUserIds.addAll(teachers.stream()
                                .map(Teacher::getUserId)
                                .collect(Collectors.toList()));
                        log.debug("通过工号精确匹配到的教师数量: {}", matchedUserIds.size());
                    }
                    break;
                    
                case NAME:
                    // 按姓名搜索时，同时搜索用户名
                    if (!StringUtils.hasText(roleType) || "学生".equals(roleType)) {
                        // 搜索学生信息
                        List<Student> students = studentMapper.selectList(
                                new LambdaQueryWrapper<Student>()
                                        .like(Student::getCollege, searchKey)
                                        .or()
                                        .like(Student::getDepartment, searchKey)
                                        .or()
                                        .like(Student::getMajor, searchKey)
                                        .select(Student::getUserId)
                        );
                        matchedUserIds.addAll(students.stream()
                                .map(Student::getUserId)
                                .collect(Collectors.toList()));
                        log.debug("按姓名匹配到的学生数量: {}", matchedUserIds.size());
                    }
                    
                    if (!StringUtils.hasText(roleType) || "教师".equals(roleType)) {
                        // 搜索教师信息
                        List<Teacher> teachers = teacherMapper.selectList(
                                new LambdaQueryWrapper<Teacher>()
                                        .like(Teacher::getDepartment, searchKey)
                                        .or()
                                        .like(Teacher::getTitle, searchKey)
                                        .select(Teacher::getUserId)
                        );
                        matchedUserIds.addAll(teachers.stream()
                                .map(Teacher::getUserId)
                                .collect(Collectors.toList()));
                        log.debug("按姓名匹配到的教师数量: {}", matchedUserIds.size());
                    }
                    
                    // 在用户表中搜索用户名
                    queryWrapper.and(wrapper -> wrapper
                            .like(User::getUsername, searchKey)
                            .or()
                            .in(!matchedUserIds.isEmpty(), User::getUserId, matchedUserIds)
                    );
                    break;
                    
                default:
                    // 未知类型，使用模糊搜索
                    if (!StringUtils.hasText(roleType) || "学生".equals(roleType)) {
                        // 模糊匹配学号
                        List<Student> students = studentMapper.selectList(
                                new LambdaQueryWrapper<Student>()
                                        .like(Student::getStudentNo, searchKey)
                                        .select(Student::getUserId)
                        );
                        matchedUserIds.addAll(students.stream()
                                .map(Student::getUserId)
                                .collect(Collectors.toList()));
                    }
                    
                    if (!StringUtils.hasText(roleType) || "教师".equals(roleType)) {
                        // 模糊匹配教师工号
                        List<Teacher> teachers = teacherMapper.selectList(
                                new LambdaQueryWrapper<Teacher>()
                                        .like(Teacher::getTeacherNo, searchKey)
                                        .select(Teacher::getUserId)
                        );
                        matchedUserIds.addAll(teachers.stream()
                                .map(Teacher::getUserId)
                                .collect(Collectors.toList()));
                    }
                    
                    // 在用户表中搜索用户名
                    queryWrapper.and(wrapper -> wrapper
                            .like(User::getUsername, searchKey)
                            .or()
                            .in(!matchedUserIds.isEmpty(), User::getUserId, matchedUserIds)
                    );
                    log.debug("模糊搜索匹配到的用户ID数量: {}", matchedUserIds.size());
                    break;
            }
        }
        
        // 3. 执行用户查询
        Page<User> userPage = this.page(page, queryWrapper);
        List<User> users = userPage.getRecords();
        log.debug("查询到的用户总数: {}", userPage.getTotal());
        
        // 4. 年级筛选（仅对学生角色有效）
        if (StringUtils.hasText(grade)) {
            if (StringUtils.hasText(roleType) && !"学生".equals(roleType)) {
                log.warn("年级筛选仅对学生角色有效，当前角色类型：{}", roleType);
            } else {
                List<Long> userIds = users.stream()
                        .map(User::getUserId)
                        .collect(Collectors.toList());
                
                if (!userIds.isEmpty()) {
                    // 查询符合年级条件的学生
                    List<Student> students = studentMapper.selectList(
                        new LambdaQueryWrapper<Student>()
                            .in(Student::getUserId, userIds)
                            .eq(Student::getGrade, grade + "级") // 添加"级"后缀以匹配数据库格式
                    );
                    
                    // 获取符合条件的学生用户ID
                    List<Long> filteredUserIds = students.stream()
                            .map(Student::getUserId)
                            .collect(Collectors.toList());
                    
                    // 过滤用户列表
                    users = users.stream()
                            .filter(user -> filteredUserIds.contains(user.getUserId()))
                            .collect(Collectors.toList());
                    
                    // 更新总记录数
                    userPage.setTotal(users.size());
                    log.debug("年级[{}]过滤后的用户数量: {}", grade, users.size());
                }
            }
        }
        
        // 5. 补充工号/学号信息
        final Map<Long, Student> studentMap = new HashMap<>();
        final Map<Long, Teacher> teacherMap = new HashMap<>();
        
        if (!users.isEmpty()) {
            List<Long> userIds = users.stream()
                    .map(User::getUserId)
                    .collect(Collectors.toList());
            
            // 获取学生信息
            if (!StringUtils.hasText(roleType) || "学生".equals(roleType)) {
                studentMap.putAll(
                    studentMapper.selectList(new LambdaQueryWrapper<Student>()
                            .in(Student::getUserId, userIds))
                            .stream()
                            .collect(Collectors.toMap(Student::getUserId, student -> student))
                );
                log.debug("获取到的学生信息数量: {}", studentMap.size());
            }
            
            // 获取教师信息
            if (!StringUtils.hasText(roleType) || "教师".equals(roleType)) {
                teacherMap.putAll(
                    teacherMapper.selectList(new LambdaQueryWrapper<Teacher>()
                            .in(Teacher::getUserId, userIds))
                            .stream()
                            .collect(Collectors.toMap(Teacher::getUserId, teacher -> teacher))
                );
                log.debug("获取到的教师信息数量: {}", teacherMap.size());
            }
        }
        
        // 6. 转换为响应对象
        List<UserPageResponse> responseList = users.stream()
                .map(user -> {
                    UserPageResponse response = new UserPageResponse();
                    BeanUtils.copyProperties(user, response);
                    
                    // 设置工号/学号和其他信息
                    if ("学生".equals(user.getRoleType())) {
                        Student student = studentMap.get(user.getUserId());
                        if (student != null) {
                            response.setJobNo(student.getStudentNo());
                            response.setDepartment(student.getDepartment());
                            response.setCollege(student.getCollege());
                            response.setMajor(student.getMajor());
                        }
                    } else if ("教师".equals(user.getRoleType())) {
                        Teacher teacher = teacherMap.get(user.getUserId());
                        if (teacher != null) {
                            response.setJobNo(teacher.getTeacherNo());
                            response.setDepartment(teacher.getDepartment());
                            response.setTitle(teacher.getTitle());
                        }
                    }
                    
                    return response;
                })
                .collect(Collectors.toList());
        
        // 7. 创建响应分页对象
        Page<UserPageResponse> responsePage = new Page<>(
                userPage.getCurrent(),
                userPage.getSize(),
                userPage.getTotal()
        );
        responsePage.setRecords(responseList);
        
        log.info("用户列表查询完成 - 总记录数: {}, 当前页记录数: {}", 
                responsePage.getTotal(), responsePage.getRecords().size());
        
        return responsePage;
    }

    /**
     * 根据用户ID更新登录时间
     * @param userId 用户ID
     */
    public void updateUserLoginTime(Long userId) {
        User user = this.getById(userId);
        if (user != null) {
            user.setLastLogin(LocalDateTime.now());
            this.updateById(user);
        }
    }

    @Override
    @Transactional
    public Boolean createUser(CreateUserRequest request) {
        try {
            // 检查用户名是否已存在
            if (this.findByUsername(request.getUsername()) != null) {
                log.warn("创建用户失败：用户名[{}]已存在", request.getUsername());
                return false;
            }

            // 使用BeanCover创建用户对象
            User user = BeanCover.coverUser(request, passwordEncoder);

            // 保存用户
            this.save(user);

            // 根据角色类型创建对应的记录
            switch (request.getRoleType()) {
                case "学生":
                    Student student = new Student();
                    student.setUserId(user.getUserId());
                    student.setStudentNo(request.getJobNo());
                    studentMapper.insert(student);
                    break;
                case "教师":
                    Teacher teacher = new Teacher();
                    teacher.setUserId(user.getUserId());
                    teacher.setTeacherNo(request.getJobNo());
                    teacherMapper.insert(teacher);
                    break;
                case "管理员":
                    // 管理员不需要额外记录
                    break;
                default:
                    log.error("创建用户失败：无效的角色类型[{}]", request.getRoleType());
                    throw new IllegalArgumentException("无效的角色类型");
            }
            
            log.info("用户[{}]创建成功，角色类型：{}", user.getUsername(), user.getRoleType());
            return true;
        } catch (Exception e) {
            log.error("创建用户失败：{}", e.getMessage(), e);
            throw e;
        }
    }
}
